package com.yuyu.spring4mvc.controller;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.catalina.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;


/**
 * Controller的demo类
 * @author iv1733
 * @RequestMapping： 可以修饰方法和类
 * 
 * REST: Representational State Transfer (资源)表现层状态转化
 * 资源：服务器上的任何一种类型的实体都可以叫资源
 * 表现层：把资源具体呈现出来的形式
 * 状态转换：通过某种手段，让服务器端发生状态转换
 * GET用来获取资源，POST新建，PUT更新，DELETE删除
 */

@Controller
@RequestMapping("/demo/requestMapping")
public class DemoRequestMappingController {
	
	public static final String view = "/demo/index";
	
	/**
	 * 这里的请求路径为   WEBROOT/demo/index
	 * 返回的响应视图文本为 prefix/return.jsp [注:可以嵌套路径使用]
	 * consumes： 指定请求的MIME
	 * produces：指定返回的MIME
	 * name: 为该映射起名
	 * value: 映射路径
	 * 	① 支持多个 value={"/a","/b"}
	 *  ② Rest风格 value="/a/{b}"
	 *  ③ Ant风格 value="/a/*",*和？两种表达式，可以看成是正则表达式的简化版
	 *  ④ 正则风格 value="/a/{id:reg}"
	 * method: RequestMethod
	 * params: 请求体中必须包含项
	 * headers: 请求头中必须包含项
	 */
	@RequestMapping("/index")
	public String index() {
		/**
		 * return 类型为字符串的时候，需要配置对应的视图解析器，才能找到相对应的路径
		 * 如果想要直接返回的话，需要使用注解@ResponseBody
		 */
		System.out.println("index");
		//还支持 forward: redirect:
		return view;
	}
	
	/**
	 * Spring支持多个路径配置
	 */
	@RequestMapping(value= {"/more/a","/more/b"})
	public String more() {
		/**
		 * return 类型为字符串的时候，需要配置对应的视图解析器，才能找到相对应的路径
		 * 如果想要直接返回的话，需要使用注解@ResponseBody
		 */
		System.out.println("more");
		return view;
	}
	
	
	/**
	 * Spring支持ant风格的路径
	 * ant有三种通配符
	 * ？：表示匹配一个字符
	 * *：表示匹配任意字符
	 * **：表示匹配任意的路径  比如  /b/b/b
	 */
	@RequestMapping(value="/ant/**/a")
	public String testAnt() {
		System.out.println("testAnt");
		return view;
	}
	
	/**
	 * Spring还支持正则表达式的通配符
	 */
	@RequestMapping("/reg/{name:[a-z]+}")
	public String testReg(@PathVariable("name") String name) {
		System.out.println("testReg ==="+name);
		return view;
	}
	
	
	@RequestMapping(value= "/rest",method=RequestMethod.GET)
	public String rest() {
		System.out.println("rest ");
		return "/demo/rest";
	}
	
	/**
	 * Spring支持Rest风格路径
	 * 表单只支持GET和POST请求
	 * 可以使用HiddenHttpMethodFilter来让正常的表单支持 CRUD操作
	 */
	@RequestMapping(value= "/rest/{id}",method=RequestMethod.GET)
	public String restGet(@PathVariable("id") Long id) {
		System.out.println("rest GET id==="+id);
		return view;
	}
	
	@RequestMapping(value= "/rest/{id}",method=RequestMethod.POST)
	public String restPost(@PathVariable("id") Long id) {
		System.out.println("rest POST id==="+id);
		return view;
	}
	
	@RequestMapping(value= "/rest/{id}",method=RequestMethod.DELETE)
	public String restDelete(@PathVariable("id") Long id) {
		System.out.println("rest DELETE id==="+id);
		return view;
	}
	
	@RequestMapping(value= "/rest/{id}",method=RequestMethod.PUT)
	public String restPut(@PathVariable("id") Long id) {
		System.out.println("rest PUT id==="+id);
		return view;
	}
	
	//===========================请求参数================================
	/**
	 * @RequestParam: 映射请求参数
	 * @RequestBody： 映射请求体
	 * @RequestHeader： 映射请求头
	 * @RequestPart： 用来映射Multipart
	 * @CookieValue: 获取Cookie
	 * 
	 * 使用POJO对象作为绑定请求参数值，会按照名称进行自动匹配，支持级联属性 address.location TODO
	 * 
	 * 使用原生的ServletAPI作为传入参数
	 *  MVC的Handler方法可以接受那些ServletAPI的参数
	 *  HttpServletRequest
	 *  HttpServletResponse
	 *  HttpSession
	 *  java.security.Principal  用户认证相关
	 *  Locale  : 本地语言相关
	 *  InputStream
	 *  OutputStream
	 *  Reader
	 *  Writer
	 *  
	 *  //返回值
	 *  ModelAndView ： 添加的模型数据会放到域对象里
	 *  Map，Model，ModelMap --》这些入参的值最终都会封装成ModelAndView
	 *  @SessionAtribute(value={"user1","user2"},types={Dept.class,A.class})
	 *   ： 前边都是放置在请求域里面，如果需要放置到session域中，则需要使用该标签
	 *   需要放置在类上面，不能放置在方法上面
	 *   可以根据名称指定，也可以根据类型指定
	 *  @ModelAttribute： 可以标注在方法和参数上
	 *  可以提前加载对象,标注在方法上，在这个类的所有方法执行之前都会执行
	 *  注意属性名要跟类名对应的字符串
	 *  
	 *  无论返回的是String，View或者ModelMap类型都会转换成ModelAndView对象，包含了逻辑名和模型对象的视图
	 *  View   ViewResolver
	 *  
	 */
	
	@ModelAttribute
	public void getUser(@RequestParam(value="id",required=false) Integer id,Map<String,Object> map) {
		if(id != null) {
			//模拟从数据库中获取对象
			//User user = new User(1,"Tom","123456","tom@atguigu.com",12);
			String user = "aaa";
			System.out.println("从数据库中获取一个对象："+user);
			map.put("user", user);
		}
	}
	
	
	
}
